﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Alipay.AopSdk.AspnetCore;
using Alipay.AopSdk.Core.Domain;
using Alipay.AopSdk.Core.Request;
using Casamiel.API.Application.Models;
using Casamiel.Application;
using Casamiel.Common;
using Casamiel.Common.Extensions;
using Casamiel.Domain;
using Casamiel.Domain.Entity;
using Casamiel.Domain.Request;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;
using PaySharp.Wechatpay;
using PaySharp.Wechatpay.Domain;
using PaySharp.Wechatpay.Request;

namespace Casamiel.API.Application.Services
{
	/// <summary>
	/// 
	/// </summary>
	public class RefundService : IRefundService
    {
        private readonly NLog.ILogger logger = LogManager.GetLogger("OrderService");
        private readonly IMemberCardService _memberCardService;
        private readonly IStoreService _storeService;
        private readonly IIcApiService _icApiService;
        private readonly ICasaMielSession _session;
        private readonly IBaseMemberConponsRepository _baseMemberConponsRepository;
        private readonly IPaymentService _paymentService;
        private readonly List<Common.MiniAppSettings> _listminiAppSettings;
        private readonly INoticeService _notice;
        private readonly IOrderService _order;
        private IConfiguration Configuration { get; }
        private readonly IMemberRepository _memberRepository;
        private readonly IInvoiceDetailRepository _invoiceDetailRepository;
        private readonly IMemberCouponRepository _memberCouponRepository;
        private readonly INetICService _netICService;
        private readonly AlipayService _alipayService;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="storeService"></param>
        /// <param name="iicApiService"></param>
        /// <param name="session"></param>
        /// <param name="paymentService"></param>
        /// <param name="mini"></param>
        /// <param name="memberCouponRepository"></param>
        /// <param name="netICService"></param>
        /// <param name="configuration"></param>
        /// <param name="memberCardService"></param>
        /// <param name="notice"></param>
        /// <param name="order"></param>
        /// <param name="invoiceDetailRepository"></param>
        /// <param name="baseMemberConponsRepository"></param>
        /// <param name="memberRepository"></param>
        /// <param name="alipayService"></param>
        public RefundService(IStoreService storeService, IIcApiService iicApiService, ICasaMielSession session, IPaymentService paymentService,
            IOptionsSnapshot<List<Common.MiniAppSettings>> mini, IMemberCouponRepository memberCouponRepository, INetICService netICService,
                                      IConfiguration configuration, IMemberCardService memberCardService, INoticeService notice, IOrderService order, IInvoiceDetailRepository invoiceDetailRepository,
                                      IBaseMemberConponsRepository baseMemberConponsRepository, IMemberRepository memberRepository,
                                      AlipayService alipayService)
        {
            if (mini == null) {
                throw new ArgumentNullException(nameof(mini));
            }

            _storeService = storeService;
            _icApiService = iicApiService;
            _session = session;
            _paymentService = paymentService;
            _listminiAppSettings = mini.Value;
            Configuration = configuration;
            _memberCardService = memberCardService;
            _notice = notice;
            _order = order;
            _invoiceDetailRepository = invoiceDetailRepository;
            _baseMemberConponsRepository = baseMemberConponsRepository;
            _memberRepository = memberRepository;
            _memberCouponRepository = memberCouponRepository;
            _netICService = netICService;
            _alipayService = alipayService;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="OutTradeNO"></param>
        /// <returns></returns>
        public async Task<Zmodel> IcchargebackByOutTradeNO(string OutTradeNO)
        {
            var payinfo = await _paymentService.FindByOutTradeNOAsync<ICasaMielSession>(OutTradeNO).ConfigureAwait(false);
            if (payinfo != null) {
               
                return await NewMethod(payinfo);
            }
            return new Zmodel { code = 999, msg = "充值记录不存在" };
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ICTradeNO"></param>
        /// <returns></returns>
        public async Task<Zmodel> Icchargeback(string ICTradeNO)
        {
            var payinfo = await _paymentService.GetByIcTradeNOAsync<ICasaMielSession>(ICTradeNO).ConfigureAwait(false);
            if (payinfo != null) {
                return await NewMethod(payinfo);
            }
            //if (payinfo.PayMethod == 6) {
            //    AlipayRefund(payinfo);
            //}
            return new Zmodel { code = 999, msg = "充值记录不存在" };

        }


        /// <summary>
        /// 订单退款
        /// </summary>
        /// <param name="tradeno">商户订单号</param>
        /// <param name="alipayTradeNo">支付宝交易号</param>
        /// <param name="refundAmount">退款金额</param>
        /// <param name="refundReason">退款原因</param>
        /// <param name="refundNo">退款单号</param>
        /// <returns></returns>
         
        private async Task<Alipay.AopSdk.Core.Response.AlipayTradeRefundResponse>   AlipayRefund(string tradeno, string alipayTradeNo, string refundAmount, string refundReason, string refundNo
           )
        {
             

             /*DefaultAopClient client = new DefaultAopClient(Config.Gatewayurl, Config.AppId, Config.PrivateKey, "json", "2.0",
			    Config.SignType, Config.AlipayPublicKey, Config.CharSet, false);*/

            AlipayTradeRefundModel model = new AlipayTradeRefundModel();
            model.OutTradeNo = tradeno;
            model.TradeNo = alipayTradeNo;
            model.RefundAmount = refundAmount;
            model.RefundReason = refundReason;
            model.OutRequestNo = refundNo;

            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            request.SetBizModel(model);

            var response = await _alipayService.ExecuteAsync(request);
            return response;
        }





        private async Task<Zmodel> NewMethod(PaymentRecord payinfo)
        {
            if (payinfo is null) {
                return new Zmodel { code = 999, msg = "充值记录不存在" };
            }

            var entity =await _invoiceDetailRepository.FindByOutTradeNOAsync<ICasaMielSession>(payinfo.OutTradeNo).ConfigureAwait(false);
            if (entity!=null){
                if (entity.Status == 0) {
                    return new Zmodel { code = 999, msg = "已开发票不能退款" };
                }
            }

            var req = new Models.ICModels.CardChargeBackReq { cardno = payinfo.BillNO, phoneno = payinfo.Mobile, tradeno = payinfo.IcTradeNO, chargemoney = payinfo.Amount };
            logger.Trace($"icchargebackReq:{JsonConvert.SerializeObject(req)}");
            var re = await _icApiService.Icchargeback(req).ConfigureAwait(false);
            logger.Trace(JsonConvert.SerializeObject(re));
            if (re.code == 0 || re.code == 272 || re.code == 275) {
                string OutRefundNo = $"R{ DateTime.Now.ToString("yyyyMMddHHmmssfff", CultureInfo.CurrentCulture) }";
                string ictradeno = "";
                if (re.code == 0) {
                    var r = JsonConvert.DeserializeObject<dynamic>(re.content);
                    ictradeno = r.tradeno;
                }

                switch (payinfo.PayMethod) {
                    case 6:
                        var a = await AlipayRefund(OutRefundNo,payinfo.OutTradeNo, $"{payinfo.Amount}","",OutRefundNo).ConfigureAwait(false);
                        if (a.Code != "10000") {
                            //var re = await Consumeback(entity, payinfo);
                            //return re;

                            return new Zmodel { code = 9999, content = JsonConvert.SerializeObject(a), msg = a.SubMsg };
                        }
                        logger.Trace($"refund:{JsonConvert.SerializeObject(a)}");
                        await NewMethod1(payinfo, OutRefundNo, a.TradeNo, entity).ConfigureAwait(false);
                        return new Zmodel { code = 0, content = JsonConvert.SerializeObject(a), msg = a.Msg };

 
                    case 1://appwechatpay
                        var gateway2 = new PaySharp.Wechatpay.Merchant {
                            AppId = Configuration.GetSection("WxPayAppSettings").GetValue<string>("AppId"),
                            MchId = Configuration.GetSection("WxPayAppSettings").GetValue<string>("MchId"),// "1498771272",//1233410002",
                            Key = Configuration.GetSection("WxPayAppSettings").GetValue<string>("Key"),
                            AppSecret = Configuration.GetSection("WxPayAppSettings").GetValue<string>("AppSecret"),// "f7ab7484a6bd1df17ca2e7cc35604459",
                            SslCertPath = Configuration.GetSection("WxPayAppSettings").GetValue<string>("SslCertPath"),//"Certs/apiclient_cert.p12",
                            SslCertPassword = Configuration.GetSection("WxPayAppSettings").GetValue<string>("SslCertPassword"),// "1233410002",
                            NotifyUrl = Configuration.GetSection("WxPayAppSettings").GetValue<string>("NotifyUrl")// _settings.AppWxpayNotify,// "http://localhost:61337/Notify"
                        };
                        var request1 = new RefundRequest();
                        request1.AddGatewayData(new RefundModel() {
                            TradeNo = payinfo.OutTradeNo,
                            RefundAmount = (payinfo.Amount * 100).ToInt32(0),
                            RefundDesc = "",
                            RefundAccount = "REFUND_SOURCE_UNSETTLED_FUNDS",
                            OutRefundNo = OutRefundNo,
                            TotalAmount = (payinfo.Amount * 100).ToInt32(0),
                            OutTradeNo = payinfo.TradeNo
                        });
                        WechatpayGateway ga1 = new WechatpayGateway(gateway2);
                        var response1 = ga1.Execute(request1);
                        if (response1.ResultCode != "SUCCESS") {

                            return new Zmodel { code = 9999, content = JsonConvert.SerializeObject(response1), msg = response1.ResultCode };
                        }
                        //var paymentr = new PaymentRecord() {
                        //    Mobile = payinfo.Mobile,
                        //    BillNO = payinfo.TradeNo,
                        //    OperationMethod = 3,
                        //    Amount = payinfo.Amount,
                        //    CreateTime = DateTime.Now,
                        //    TradeNo = OutRefundNo,
                        //    OutTradeNo = response1.RefundNo,
                        //    PayMethod = 4,
                        //    MchId = payinfo.MchId,
                        //    State = 1,
                        //    LastOperationTime = DateTime.Now,
                        //    IcTradeNO = ictradeno,
                        //    OperationState = 1,
                        //    Remark = "小程序微信支付"
                        //};
                        //await _paymentService.AddAsync<ICasaMielSession>(paymentr).ConfigureAwait(false);
                        await NewMethod1(payinfo, OutRefundNo, response1.RefundNo, entity).ConfigureAwait(false);
                        logger.Trace($"refund:{JsonConvert.SerializeObject(response1)}");
                        return new Zmodel { code = 0, content = JsonConvert.SerializeObject(response1), msg = response1.ReturnMsg };

                    case 2://alipay
                        var merchant = new PaySharp.Alipay.Merchant() {
                            AppId = Configuration.GetSection("AlipaySettings").GetValue<string>("AppId"),// "2018012302035911",
                            NotifyUrl = Configuration.GetSection("AlipaySettings").GetValue<string>("NotifyUrl"),//"http://xiaoha.zicp.net:10154/Notify",//
                            ReturnUrl = Configuration.GetSection("AlipaySettings").GetValue<string>("ReturnUrl"),//"http://xiaoha.zicp.net:10154/Notify1",//
                            AlipayPublicKey = Configuration.GetSection("AlipaySettings").GetValue<string>("AlipayPublicKey"),
                            Privatekey = Configuration.GetSection("AlipaySettings").GetValue<string>("Privatekey")
                        };
                        var alipayrequest = new PaySharp.Alipay.Request.RefundRequest();
                        alipayrequest.AddGatewayData(new PaySharp.Alipay.Domain.RefundModel() {
                            TradeNo = payinfo.OutTradeNo,
                            RefundAmount = payinfo.Amount,
                            RefundReason = "",
                            OutRefundNo = OutRefundNo,
                            OutTradeNo = payinfo.TradeNo

                        });
                        PaySharp.Alipay.AlipayGateway gateway = new PaySharp.Alipay.AlipayGateway(merchant);
                        var alipayresponse = gateway.Execute(alipayrequest);
                        if (alipayresponse.Code != "10000") {
                            //var re = await Consumeback(entity, payinfo);
                            //return re;

                            return new Zmodel { code = 9999, content = JsonConvert.SerializeObject(alipayresponse), msg = alipayresponse.SubMessage };
                        }
                        logger.Trace($"refund:{JsonConvert.SerializeObject(alipayresponse)}");
                        await NewMethod1(payinfo, OutRefundNo, alipayresponse.TradeNo,entity).ConfigureAwait(false);
                        return new Zmodel { code = 0, content = JsonConvert.SerializeObject(alipayresponse), msg = alipayresponse.Message };
                    // break;
                    case 4:
                        var _miniAppSettings = _listminiAppSettings.Where(c => c.MchId == payinfo.MchId).FirstOrDefault();
                        var gateway1 = new PaySharp.Wechatpay.Merchant {
                            AppId = _miniAppSettings.appid,
                            MchId = _miniAppSettings.MchId,// "1498771272",//1233410002",
                            Key = _miniAppSettings.Key,//"10adc3549ba6abe56e056f23f83e71dA",
                            AppSecret = _miniAppSettings.AppSecret,// "f7ab7484a6bd1df17ca2e7cc35604459",
                            SslCertPath = _miniAppSettings.SslCertPath,//"Certs/apiclient_cert.p12",
                            SslCertPassword = _miniAppSettings.SslCertPassword,// "1233410002",
                            NotifyUrl = _miniAppSettings.NotifyUrl + "/" + _miniAppSettings.appid// _settings.AppWxpayNotify,// "http://localhost:61337/Notify"
                        };
                        var request = new RefundRequest();
                        request.AddGatewayData(new RefundModel() {
                            TradeNo = payinfo.OutTradeNo,
                            RefundAmount = (payinfo.Amount * 100).ToInt32(0),
                            RefundDesc = "",
                            RefundAccount = "REFUND_SOURCE_UNSETTLED_FUNDS",
                            OutRefundNo = OutRefundNo,
                            TotalAmount = (payinfo.Amount * 100).ToInt32(0),
                            OutTradeNo = payinfo.TradeNo
                        });
                        WechatpayGateway ga = new WechatpayGateway(gateway1);
                        var response = ga.Execute(request);
                        if (response.ResultCode != "SUCCESS") {

                            return new Zmodel { code = 9999, content = JsonConvert.SerializeObject(response), msg = response.ErrCodeDes };
                        }
                        //var payment = new PaymentRecord() {
                        //    Mobile = payinfo.Mobile,
                        //    BillNO = payinfo.TradeNo,
                        //    OperationMethod = 3,
                        //    Amount = payinfo.Amount,
                        //    CreateTime = DateTime.Now,
                        //    TradeNo = OutRefundNo,
                        //    OutTradeNo = response.RefundNo,
                        //    PayMethod = 4,
                        //    MchId = payinfo.MchId,
                        //    State = 1,
                        //    OperationState = 1,
                        //    LastOperationTime = DateTime.Now,
                        //    IcTradeNO = ictradeno,
                        //    Remark = "小程序微信支付"
                        //};
                        await NewMethod1(payinfo,OutRefundNo, response.RefundNo, entity).ConfigureAwait(false);
                        //await _paymentService.AddAsync<ICasaMielSession>(payment).ConfigureAwait(false);
                        logger.Trace($"refund:{JsonConvert.SerializeObject(response)}");
                        return new Zmodel { code = 0, content = JsonConvert.SerializeObject(response), msg = response.ReturnMsg };


                    default:
                        break;
                }
            }
            return re;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="payinfo"></param>
        /// <param name="OutRefundNo"></param>
        /// <param name="TradeNo"></param>
        /// <param name="entity"></param>
        /// <returns></returns>
        private async Task NewMethod1(PaymentRecord payinfo, string OutRefundNo,string TradeNo,InvoiceDetail entity)
        {
            var paymenta = new PaymentRecord() {
                Mobile = payinfo.Mobile,
                BillNO = payinfo.TradeNo,
                OperationMethod = 3,
                Amount = payinfo.Amount,
                CreateTime = DateTime.Now,
                TradeNo = OutRefundNo,
                OutTradeNo = TradeNo,
                PayMethod = 2,
                MchId = payinfo.MchId,
                State = 1,
                OperationState = 1,
                LastOperationTime = DateTime.Now,
                IcTradeNO = payinfo.IcTradeNO,
                Remark = payinfo.Remark
            };
            await _paymentService.AddAsync<ICasaMielSession>(paymenta).ConfigureAwait(false);
            if (entity != null) {
                entity.Status = -1;
              await  _invoiceDetailRepository.UpdateAsync<ICasaMielSession>(entity).ConfigureAwait(false);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="OrderCode"></param>
        /// <returns></returns>
        public async Task<Zmodel> GroupPurchaseOrderRefund(string OrderCode)
        {
            var payinfo = await _paymentService.FindAsync<ICasaMielSession>(OrderCode, (int)OperationMethod.GroupPurchase, 1).ConfigureAwait(false);
            if (payinfo == null) {
                return new Zmodel { code = 0, msg = "未支付订单" };
            }
            var list = await _memberCouponRepository.GetListAsnyc<ICasaMielSession>(OrderCode).ConfigureAwait(false);
            if(list!=null && list.Any()) {
                foreach (var item in list) {
                 var ticketInfoRsp = await _netICService.Tmticketquery(new Domain.Request.IC.TmticketqueryReq { ticketcode = item.Ticketcode }).ConfigureAwait(false);
                    if (ticketInfoRsp.code == 0) {
                        //"content": "{\"wxopenid\":\"\",\"ticketcode\":\"383836883066537215\",\"productid\",278048,\"productname\":\"蜜兒10元提货券(160*65)mm\",\"customername\":\"招银网络科技（深圳）有限公司\",\"price\":10.00,\"state\":3,\"description\":\"可使用\",\"startdate\":\"2019-04-02 00:00:00\",\"enddate\":\"2022-06-29 23:59:55\"}",
                        var ticketInfo = JObject.Parse(ticketInfoRsp.content);

                        //a.Price = ticketInfo["price"].ToString().ToDecimal(0);
                        //a.Productname = ticketInfo["productname"].ToString();
                        //a.Productid = ticketInfo["productid"].ToInt64(0);
                        var state = ticketInfo["state"].ToInt16(0);
                        if (state == 0) {
                            return new Zmodel { code = 999, msg = "券已使用不能退款" };
                        } else if (state == -2) {
                            return new Zmodel { code = 999, msg = "券已转赠不能退款" };
                        }

                    }    

                }

                foreach (var item in list) {
                    var icresult = await _netICService.Tmticketchange(new Domain.Request.TmticketchangeRequest { Ticketcode = item.Ticketcode }).ConfigureAwait(false);
                    if (icresult.code == 0) {
                        //{"code":0,"content":"{\"newticketid\":58589790,\"newticketcode\":\"383836883066537215\",\"ticketid\":58589789,\"ticketcode\":\"305888238862533476\"}"
                        var d = JObject.Parse(icresult.content);
                        var a = new BaseMemberCoupons {
                            CreateTime = DateTime.Now,
                             ProductId=item.Productid,
                            TicketCode = d["newticketcode"].ToString(),
                            State=1,
                             Price=item.Price,Productname=item.Productname
                        };
                        using (var uow = _session.UnitOfWork(IsolationLevel.Serializable)) {
                           await _memberCouponRepository.DeleteAsync(item, uow);
                           await _baseMemberConponsRepository.SaveAsync(a, uow);
                        }

                    }
                }
            }





            var re = new Zmodel { code = 0, msg = "" };
            string OutRefundNo = "R" + DateTime.Now.ToString("yyyyMMddHHmmssfff", CultureInfo.CurrentCulture);

            switch (payinfo.PayMethod) {
                case (int)PayMethod.WechatPayApp://appwechatpay
                    var gateway2 = new PaySharp.Wechatpay.Merchant {
                        AppId = Configuration.GetSection("WxPayAppSettings").GetValue<string>("AppId"),
                        MchId = Configuration.GetSection("WxPayAppSettings").GetValue<string>("MchId"),// "1498771272",//1233410002",
                        Key = Configuration.GetSection("WxPayAppSettings").GetValue<string>("Key"),
                        AppSecret = Configuration.GetSection("WxPayAppSettings").GetValue<string>("AppSecret"),// "f7ab7484a6bd1df17ca2e7cc35604459",
                        SslCertPath = Configuration.GetSection("WxPayAppSettings").GetValue<string>("SslCertPath"),//"Certs/apiclient_cert.p12",
                        SslCertPassword = Configuration.GetSection("WxPayAppSettings").GetValue<string>("SslCertPassword"),// "1233410002",
                        NotifyUrl = Configuration.GetSection("WxPayAppSettings").GetValue<string>("NotifyUrl")// _settings.AppWxpayNotify,// "http://localhost:61337/Notify"
                    };
                    var request1 = new RefundRequest();
                    request1.AddGatewayData(new RefundModel() {
                        TradeNo = payinfo.OutTradeNo,
                        RefundAmount = (payinfo.Amount * 100).ToInt32(0),
                        RefundDesc = "",
                        RefundAccount = "REFUND_SOURCE_UNSETTLED_FUNDS",
                        OutRefundNo = payinfo.TradeNo.Replace("C", "R", StringComparison.InvariantCulture),
                        TotalAmount = (payinfo.Amount * 100).ToInt32(0),
                        OutTradeNo = payinfo.TradeNo
                    });
                    WechatpayGateway ga1 = new WechatpayGateway(gateway2);
                    var response1 = ga1.Execute(request1);
                    logger.Trace($"{JsonConvert.SerializeObject(response1)}");
                    if (response1.ResultCode == "SUCCESS") {
                        var en = await _paymentService.FindAsync<ICasaMielSession>(payinfo.TradeNo.Replace("C", "R", StringComparison.InvariantCulture)).ConfigureAwait(false);
                        if (en == null) {
                            var paymentr = new PaymentRecord() {
                                Mobile = payinfo.Mobile,
                                BillNO = payinfo.TradeNo,
                                OperationMethod = (int)OperationMethod.Refund,
                                Amount = payinfo.Amount,
                                CreateTime = DateTime.Now,
                                TradeNo = payinfo.TradeNo.Replace("C", "R"),
                                OutTradeNo = response1.RefundNo,
                                PayMethod = payinfo.PayMethod,
                                MchId = payinfo.MchId,
                                State = 1,
                                LastOperationTime = DateTime.Now,
                                OperationState = 1,
                                Remark = payinfo.Remark
                            };
                            await _paymentService.AddAsync<ICasaMielSession>(paymentr).ConfigureAwait(false);
                        }
                        //var re = await Consumeback(entity, payinfo);
                        return re;
                    }
                    return new Zmodel { code = 9999, content = response1.ReturnMsg, msg = response1.ErrCodeDes };
                //break;
                case (int)PayMethod.Alipay://alipay
                    var merchant = new PaySharp.Alipay.Merchant() {
                        AppId = Configuration.GetSection("AlipaySettings").GetValue<string>("AppId"),// "2018012302035911",
                        NotifyUrl = Configuration.GetSection("AlipaySettings").GetValue<string>("NotifyUrl"),//"http://xiaoha.zicp.net:10154/Notify",//
                        ReturnUrl = Configuration.GetSection("AlipaySettings").GetValue<string>("ReturnUrl"),//"http://xiaoha.zicp.net:10154/Notify1",//
                        AlipayPublicKey = Configuration.GetSection("AlipaySettings").GetValue<string>("AlipayPublicKey"),
                        Privatekey = Configuration.GetSection("AlipaySettings").GetValue<string>("Privatekey")
                    };
                    var alipayrequest = new PaySharp.Alipay.Request.RefundRequest();
                    alipayrequest.AddGatewayData(new PaySharp.Alipay.Domain.RefundModel() {
                        TradeNo = payinfo.OutTradeNo,
                        RefundAmount = payinfo.Amount,
                        RefundReason = "",
                        OutRefundNo = payinfo.TradeNo + "1",
                        OutTradeNo = payinfo.TradeNo

                    });
                    PaySharp.Alipay.AlipayGateway gateway = new PaySharp.Alipay.AlipayGateway(merchant);
                    var alipayresponse = gateway.Execute(alipayrequest);
                    if (alipayresponse.Code == "10000") {
                        var paymentr = new PaymentRecord() {
                            Mobile = payinfo.Mobile,
                            BillNO = payinfo.TradeNo,
                            OperationMethod = (int)OperationMethod.Refund,
                            Amount = payinfo.Amount,
                            CreateTime = DateTime.Now,
                            TradeNo = OutRefundNo,
                            OutTradeNo = alipayresponse.TradeNo,
                            PayMethod = (int)PayMethod.Alipay,
                            MchId = payinfo.MchId,
                            State = 1,
                            LastOperationTime = DateTime.Now,
                            OperationState = 1,
                            Remark = payinfo.Remark
                        };
                        await _paymentService.AddAsync<ICasaMielSession>(paymentr).ConfigureAwait(false);
                        logger.Trace($"refund:{JsonConvert.SerializeObject(alipayresponse)}");
                        //var re = await Consumeback(entity, payinfo);
                        return re;
                    }

                    return new Zmodel { code = 9999, content = alipayresponse.Message, msg = alipayresponse.SubMessage };
                // break;
                case (int)PayMethod.WechatMiniPay:
                    var _miniappsetting = _listminiAppSettings.Where(c => c.MchId == payinfo.MchId).FirstOrDefault();
                    var gateway1 = new PaySharp.Wechatpay.Merchant {
                        AppId = _miniappsetting.appid,
                        MchId = _miniappsetting.MchId,// "1498771272",//1233410002",
                        Key = _miniappsetting.Key,//"10adc3549ba6abe56e056f23f83e71dA",
                        AppSecret = _miniappsetting.AppSecret,// "f7ab7484a6bd1df17ca2e7cc35604459",
                        SslCertPath = _miniappsetting.SslCertPath,//"Certs/apiclient_cert.p12",
                        SslCertPassword = _miniappsetting.SslCertPassword,// "1233410002",
                        NotifyUrl = _miniappsetting.NotifyUrl + "/" + _miniappsetting.appid// _settings.AppWxpayNotify,// "http://localhost:61337/Notify"
                    };
                    logger.Trace($"_miniAppSettings{JsonConvert.SerializeObject(_listminiAppSettings)}");
                    var request = new RefundRequest();
                    request.AddGatewayData(new RefundModel() {
                        TradeNo = payinfo.OutTradeNo,
                        RefundAmount = (payinfo.Amount * 100).ToInt32(0),
                        RefundDesc = "",
                        RefundAccount = "REFUND_SOURCE_UNSETTLED_FUNDS",
                        OutRefundNo = payinfo.TradeNo.Replace("C", "R", StringComparison.CurrentCultureIgnoreCase),
                        TotalAmount = (payinfo.Amount * 100).ToInt32(0),
                        OutTradeNo = payinfo.TradeNo
                    });
                    WechatpayGateway ga = new WechatpayGateway(gateway1);
                    if (!string.IsNullOrEmpty(_miniappsetting.GatewayUrl)) {
                        ga.GatewayUrl = _miniappsetting.GatewayUrl;
                    }

                    var response = ga.Execute(request);
                    logger.Trace($"refund:{JsonConvert.SerializeObject(response)}");
                    if (response.ResultCode == "SUCCESS") {
                        var en = await _paymentService.FindAsync<ICasaMielSession>(payinfo.TradeNo.Replace("C", "R", StringComparison.CurrentCultureIgnoreCase)).ConfigureAwait(false);
                        if (en == null) {
                            var paymentr = new PaymentRecord() {
                                Mobile = payinfo.Mobile,
                                BillNO = payinfo.TradeNo,
                                OperationMethod = (int)OperationMethod.Refund,
                                Amount = payinfo.Amount,
                                CreateTime = DateTime.Now,
                                TradeNo = payinfo.TradeNo.Replace("C", "R", StringComparison.CurrentCultureIgnoreCase),
                                OutTradeNo = response.RefundNo,
                                PayMethod = (int)PayMethod.WechatMiniPay,
                                MchId = payinfo.MchId,
                                State = 1,
                                LastOperationTime = DateTime.Now,
                                OperationState = 1,
                                Remark = payinfo.Remark
                            };
                            await _paymentService.AddAsync<ICasaMielSession>(paymentr).ConfigureAwait(false);
                        }
                        return re;
                    }

                    return new Zmodel { code = 9999, content = response.ReturnCode, msg = response.ReturnMsg };


                //break;
                default:
                    break;
            }
            return new Zmodel { };
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<Zmodel> OrderRefund(OrderRefundReq data)
        {
            if (data == null) {
                throw new ArgumentNullException(nameof(data));
            }

            var cancelReason = data.CancelReason;
            // var mobile = MemberHelper.GetMobile(token);
            var entity = await _order.GetByOrderCodeAsync<ICasaMielSession>(data.OrderCode).ConfigureAwait(false);

            if (entity == null) {
                return new Zmodel { code = 9999, content = "", msg = "订单不存在" };
            }
            entity.CancelReason = cancelReason;
            if (entity.Source == 0 || entity.Source == 7 || entity.Source == 8 || entity.Source == 11) {
                var operationMethod = OperationMethod.CakeStore;
                if (entity.Source == 7) {
                    operationMethod = OperationMethod.Mall;//全国配
                }
                if (entity.Source == 8) {
                    operationMethod = OperationMethod.Waimai;//外卖
                }
                if (entity.Source == 11) {
                    operationMethod = OperationMethod.Pre;//预点单
                }

                var payinfo = await _paymentService.FindAsync<ICasaMielSession>(entity.OrderCode, (int)operationMethod, 1).ConfigureAwait(false);
                if (payinfo == null) {
                    return new Zmodel { code = 0, msg = "未支付订单" };
                }


                var re = await Consumeback(entity).ConfigureAwait(false);

                double EPSILON = 0.00000001;
                if (Math.Abs(payinfo.Amount - 0) < EPSILON) {
                    return re;
                }
                string OutRefundNo = "R" + DateTime.Now.ToString("yyyyMMddHHmmssfff", CultureInfo.CurrentCulture);
                //  var re = await Consumeback(entity, payinfo);
                if (re.code == 0 || re.code == 205) {
                    switch (payinfo.PayMethod) {
                        case (int)PayMethod.WechatPayApp://appwechatpay
                            var gateway2 = new PaySharp.Wechatpay.Merchant {
                                AppId = Configuration.GetSection("WxPayAppSettings").GetValue<string>("AppId"),
                                MchId = Configuration.GetSection("WxPayAppSettings").GetValue<string>("MchId"),// "1498771272",//1233410002",
                                Key = Configuration.GetSection("WxPayAppSettings").GetValue<string>("Key"),
                                AppSecret = Configuration.GetSection("WxPayAppSettings").GetValue<string>("AppSecret"),// "f7ab7484a6bd1df17ca2e7cc35604459",
                                SslCertPath = Configuration.GetSection("WxPayAppSettings").GetValue<string>("SslCertPath"),//"Certs/apiclient_cert.p12",
                                SslCertPassword = Configuration.GetSection("WxPayAppSettings").GetValue<string>("SslCertPassword"),// "1233410002",
                                NotifyUrl = Configuration.GetSection("WxPayAppSettings").GetValue<string>("NotifyUrl")// _settings.AppWxpayNotify,// "http://localhost:61337/Notify"
                            };
                            var request1 = new RefundRequest();
                            request1.AddGatewayData(new RefundModel() {
                                TradeNo = payinfo.OutTradeNo,
                                RefundAmount = (payinfo.Amount * 100).ToInt32(0),
                                RefundDesc = "",
                                RefundAccount = "REFUND_SOURCE_UNSETTLED_FUNDS",
                                OutRefundNo = payinfo.TradeNo.Replace("C", "R", StringComparison.InvariantCulture),
                                TotalAmount = (payinfo.Amount * 100).ToInt32(0),
                                OutTradeNo = payinfo.TradeNo
                            });
                            WechatpayGateway ga1 = new WechatpayGateway(gateway2);
                            var response1 = ga1.Execute(request1);
                            logger.Trace($"{JsonConvert.SerializeObject(response1)}");
                            if (response1.ResultCode == "SUCCESS") {
                                var en = await _paymentService.FindAsync<ICasaMielSession>(payinfo.TradeNo.Replace("C", "R", StringComparison.InvariantCulture)).ConfigureAwait(false);
                                if (en == null) {
                                    var paymentr = new PaymentRecord() {
                                        Mobile = payinfo.Mobile,
                                        BillNO = payinfo.TradeNo,
                                        OperationMethod = (int)OperationMethod.Refund,
                                        Amount = payinfo.Amount,
                                        CreateTime = DateTime.Now,
                                        TradeNo = payinfo.TradeNo.Replace("C", "R"),
                                        OutTradeNo = response1.RefundNo,
                                        PayMethod = payinfo.PayMethod,
                                        MchId = payinfo.MchId,
                                        State = 1,
                                        LastOperationTime = DateTime.Now,
                                        OperationState = 1,
                                        Remark = payinfo.Remark
                                    };
                                    await _paymentService.AddAsync<ICasaMielSession>(paymentr).ConfigureAwait(false);
                                }
                                //var re = await Consumeback(entity, payinfo);
                                return re;
                            }
                            return new Zmodel { code = 9999, content = response1.ReturnMsg, msg = response1.ErrCodeDes };
                        //break;
                        case (int)PayMethod.Alipay://alipay
                            var merchant = new PaySharp.Alipay.Merchant() {
                                AppId = Configuration.GetSection("AlipaySettings").GetValue<string>("AppId"),// "2018012302035911",
                                NotifyUrl = Configuration.GetSection("AlipaySettings").GetValue<string>("NotifyUrl"),//"http://xiaoha.zicp.net:10154/Notify",//
                                ReturnUrl = Configuration.GetSection("AlipaySettings").GetValue<string>("ReturnUrl"),//"http://xiaoha.zicp.net:10154/Notify1",//
                                AlipayPublicKey = Configuration.GetSection("AlipaySettings").GetValue<string>("AlipayPublicKey"),
                                Privatekey = Configuration.GetSection("AlipaySettings").GetValue<string>("Privatekey")
                            };
                            var alipayrequest = new PaySharp.Alipay.Request.RefundRequest();
                            alipayrequest.AddGatewayData(new PaySharp.Alipay.Domain.RefundModel() {
                                TradeNo = payinfo.OutTradeNo,
                                RefundAmount = payinfo.Amount,
                                RefundReason = "",
                                OutRefundNo = payinfo.TradeNo + "1",
                                OutTradeNo = payinfo.TradeNo

                            });
                            PaySharp.Alipay.AlipayGateway gateway = new PaySharp.Alipay.AlipayGateway(merchant);
                            var alipayresponse = gateway.Execute(alipayrequest);
                            if (alipayresponse.Code == "10000") {
                                var paymentr = new PaymentRecord() {
                                    Mobile = payinfo.Mobile,
                                    BillNO = payinfo.TradeNo,
                                    OperationMethod = (int)OperationMethod.Refund,
                                    Amount = payinfo.Amount,
                                    CreateTime = DateTime.Now,
                                    TradeNo = OutRefundNo,
                                    OutTradeNo = alipayresponse.TradeNo,
                                    PayMethod = (int)PayMethod.Alipay,
                                    MchId = payinfo.MchId,
                                    State = 1,
                                    LastOperationTime = DateTime.Now,
                                    OperationState = 1,
                                    Remark = payinfo.Remark
                                };
                                await _paymentService.AddAsync<ICasaMielSession>(paymentr).ConfigureAwait(false);
                                logger.Trace($"refund:{JsonConvert.SerializeObject(alipayresponse)}");
                                //var re = await Consumeback(entity, payinfo);
                                return re;
                            }

                            return new Zmodel { code = 9999, content = alipayresponse.Message, msg = alipayresponse.SubMessage };
                        // break;
                        case (int)PayMethod.WechatMiniPay:
                            var _miniappsetting = _listminiAppSettings.Where(c => c.MchId == payinfo.MchId).FirstOrDefault();
                            var gateway1 = new PaySharp.Wechatpay.Merchant {
                                AppId = _miniappsetting.appid,
                                MchId = _miniappsetting.MchId,// "1498771272",//1233410002",
                                Key = _miniappsetting.Key,//"10adc3549ba6abe56e056f23f83e71dA",
                                AppSecret = _miniappsetting.AppSecret,// "f7ab7484a6bd1df17ca2e7cc35604459",
                                SslCertPath = _miniappsetting.SslCertPath,//"Certs/apiclient_cert.p12",
                                SslCertPassword = _miniappsetting.SslCertPassword,// "1233410002",
                                NotifyUrl = _miniappsetting.NotifyUrl + "/" + _miniappsetting.appid// _settings.AppWxpayNotify,// "http://localhost:61337/Notify"
                            };
                            logger.Trace($"_miniAppSettings{JsonConvert.SerializeObject(_listminiAppSettings)}");
                            var request = new RefundRequest();
                            request.AddGatewayData(new RefundModel() {
                                TradeNo = payinfo.OutTradeNo,
                                RefundAmount = (payinfo.Amount * 100).ToInt32(0),
                                RefundDesc = "",
                                RefundAccount = "REFUND_SOURCE_UNSETTLED_FUNDS",
                                OutRefundNo = payinfo.TradeNo.Replace("C", "R", StringComparison.CurrentCultureIgnoreCase),
                                TotalAmount = (payinfo.Amount * 100).ToInt32(0),
                                OutTradeNo = payinfo.TradeNo
                            });
                            WechatpayGateway ga = new WechatpayGateway(gateway1);
                            if (!string.IsNullOrEmpty(_miniappsetting.GatewayUrl)) {
                                ga.GatewayUrl = _miniappsetting.GatewayUrl;
                            }

                            var response = ga.Execute(request);
                            logger.Trace($"refund:{JsonConvert.SerializeObject(response)}");
                            if (response.ResultCode == "SUCCESS") {
                                var en = await _paymentService.FindAsync<ICasaMielSession>(payinfo.TradeNo.Replace("C", "R", StringComparison.CurrentCultureIgnoreCase)).ConfigureAwait(false);
                                if (en == null) {
                                    var paymentr = new PaymentRecord() {
                                        Mobile = payinfo.Mobile,
                                        BillNO = payinfo.TradeNo,
                                        OperationMethod = (int)OperationMethod.Refund,
                                        Amount = payinfo.Amount,
                                        CreateTime = DateTime.Now,
                                        TradeNo = payinfo.TradeNo.Replace("C", "R", StringComparison.CurrentCultureIgnoreCase),
                                        OutTradeNo = response.RefundNo,
                                        PayMethod = (int)PayMethod.WechatMiniPay,
                                        MchId = payinfo.MchId,
                                        State = 1,
                                        LastOperationTime = DateTime.Now,
                                        OperationState = 1,
                                        Remark = payinfo.Remark
                                    };
                                    await _paymentService.AddAsync<ICasaMielSession>(paymentr).ConfigureAwait(false);
                                }
                                return re;
                            }

                            return new Zmodel { code = 9999, content = response.ReturnCode, msg = response.ReturnMsg };


                        //break;
                        default:
                            break;
                    }

                }


                return re;
            } else {
                var rsp = await Consumeback(entity).ConfigureAwait(false);
                return rsp;

            }
            //return new Zmodel { code = 9999, content = "", msg = "订单来源"+entity.Source };
        }
        /// <summary>
        /// Consumeback the specified entity.
        /// </summary>
        /// <returns>The consumeback.</returns>
        /// <param name="entity">Entity.</param>
        private async Task<Zmodel> Consumeback(OrderBaseEntity entity)
        {
            //var _cardno = "";
            //var cardlist = await _memberCardService.GetListAsync<ICasaMielSession>(payinfo.Mobile);

            //if (cardlist != null && cardlist.Where(c => c.IsBind == true).Count() > 0)
            //{
            //    var vipcard = cardlist.Where(c => c.IsBind == true && c.CardType != "3").SingleOrDefault();
            //    if (vipcard != null)
            //    {
            //        _cardno = vipcard.CardNO;
            //    }
            //}
            var backdto = new IcConsumeBackReq { Tradeno = entity.IcTradeNO };// new IcConsumeBackReq { cardno = _cardno, tradeno = payinfo.IcTradeNO, phoneno = payinfo.Mobile };
            logger.Trace($"{JsonConvert.SerializeObject(backdto)}");

            var re = await _icApiService.Icconsumeback(backdto).ConfigureAwait(false);
            logger.Trace($"icconsumeback:{JsonConvert.SerializeObject(re)}");
            if (re.code == 0 || re.code == 205) {
                JObject obj = JsonConvert.DeserializeObject<JObject>(re.content);
                logger.Trace($"OrderCode:{entity.OrderCode},tradeno_origin:{obj["tradeno_origin"].ToString()},tradeno:{obj["tradeno"].ToString()},");
                var billno = obj["tradeno"].ToString();
                entity.ResBillNo = billno;
                if (entity.OrderType == 1) {
                    using (var uow = _session.UnitOfWork(IsolationLevel.Serializable)) {
                        entity.CloseTime = DateTime.Now;
                        entity.OrderStatus = (int)OrderStatus.Cancelled;

                        var s = await _order.OrderBaseUPdateAsync(entity, uow).ConfigureAwait(true);
                        var take = await _order.UpdateOrderTakeStatus(entity.OrderBaseId, -1, billno, uow).ConfigureAwait(true);
                        var dis = await _order.UpdateOrderDiscountStatus(entity.OrderBaseId, 1, uow).ConfigureAwait(true);
                        var noticEntity = new NoticeBaseEntity() {
                            RemindTime = DateTime.Now.AddMinutes(-3),
                            CreateTime = DateTime.Now,
                            RelationId = entity.OrderBaseId,
                            StoreId = entity.StoreId,
                            NoticeType = 4
                        };
                        await _notice.AddAsync(noticEntity, uow).ConfigureAwait(true);
                    }
                } else {
                    using (var uow = _session.UnitOfWork(IsolationLevel.Serializable)) {
                        entity.CloseTime = DateTime.Now;
                        entity.OrderStatus = (int)OrderStatus.Cancelled; ;
                        var s = await _order.OrderBaseUPdateAsync(entity, uow).ConfigureAwait(true);
                        var noticEntity = new NoticeBaseEntity() {
                            RemindTime = DateTime.Now.AddMinutes(-3),
                            CreateTime = DateTime.Now,
                            RelationId = entity.OrderBaseId,
                            StoreId = entity.StoreId,
                            NoticeType = 4
                        };
                        await _notice.AddAsync(noticEntity, uow).ConfigureAwait(true);
                    }
                }

            }
            return re;
        }
    }
}
